#include <U8g2lib.h>

//你想要的12位数据
//char yourcode[12]="123456789012";
//char yourcode[14] = "978711135407";  //13留给校验位，14留给'\0',为了能输出
 char yourcode[12]="123456564563";
// char yourcode[12]="978058784322";

int code[13] = { 0 };

char output[95] = { 0 };

int parity_table[][6] = {
  { 1, 1, 1, 1, 1, 1 },
  { 1, 1, 0, 1, 0, 0 },
  { 1, 1, 0, 0, 1, 0 },
  { 1, 1, 0, 0, 0, 1 },
  { 1, 0, 1, 1, 0, 0 },
  { 1, 0, 0, 1, 1, 0 },
  { 1, 0, 0, 0, 1, 1 },
  { 1, 0, 1, 0, 1, 0 },
  { 1, 0, 1, 0, 0, 1 },
  { 1, 0, 0, 1, 0, 1 }
};

char encoding_table[10][3][8] = {
  { "0001101", "0100111", "1110010" },
  { "0011001", "0110011", "1100110" },
  { "0010011", "0011011", "1101100" },
  { "0111101", "0100001", "1000010" },
  { "0100011", "0011101", "1011100" },
  { "0110001", "0111001", "1001110" },
  { "0101111", "0000101", "1010000" },
  { "0111011", "0010001", "1000100" },
  { "0110111", "0001001", "1001000" },
  { "0001011", "0010111", "1110100" }
};

int odd[6] = { 0 };
int even[6] = { 0 };


//屏幕
//U8G2_ST7565_ERC12864_ALT_F_4W_SW_SPI u8g2(U8G2_R2, /* clock=*/26, /* data=*/27, /* cs=*/23, /* dc=*/25, /* reset=*/24);
U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ A2, /* dc=*/ A1, /* reset=*/ A0);
//D0:SPI的时钟线SCLK
//D1:SPI的数据线SDIN

void setup() {
  Serial.begin(9600);
  u8g2.begin();
  u8g2.setContrast(0);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_ncenB08_tr);
  //u8g2.drawStr(0, 10, "Hello World!");
  //u8g2.sendBuffer();
  //delay(500);
  Serial.println();
}

void loop() {
  make_sand_code(yourcode);
  copy_to_code(yourcode, code);
  get_odd_even(code, odd, even);
  int a = calculate_check_digit(odd, even);
  Serial.print("Jiao-Yan:");
  Serial.println(a);
  code[12] = a;
  encode(output, code);
  Serial.print("before:");
  Serial.println(output);
  

  //绘制条形码
  u8g2.clearBuffer();
  u8g2.setDrawColor(1);
  u8g2.drawBox(0, 0, 128, 64);

  for (int i = 0; i < 95; i++) {
    if (output[i] == '1') {
      u8g2.setDrawColor(0);  //黑
      if (i == 0 || i == 2 || i == 46 || i == 48 || i == 92 || i == 94) {
        u8g2.drawLine(i + 10, 0, i + 10, 50);
      } else {
        u8g2.drawLine(i + 10, 0, i + 10, 45);
      }
    }
  }
  yourcode[12] = a + '0';
  u8g2.setDrawColor(0);  //黑
  char data1[7] = { 0 };
  data1[6] = '\0';
  memcpy(data1, yourcode + 1, 6);
  u8g2.drawStr(17, 56, data1);
  memcpy(data1, yourcode + 7, 6);
  u8g2.drawStr(63, 56, data1);
  memcpy(data1, yourcode , 1);
  data1[1]='\0';
  u8g2.drawStr(3, 56, data1);
  u8g2.sendBuffer();

  //解码
  // int data[13] = { 0 };
  // decoding(output, data);
  // Serial.print("after :");
  // Serial.println(output);
  // for (int i = 0; i < 13; i++) {
  //   Serial.print(data[i]);
  // }

  delay(1000);
}

void copy_to_code(char* pyourcode, int* pcode) {
  for (int i = 0; i < 12; i++) {
    pcode[i] = pyourcode[i] - '0';
  }
}

//产生随机的数据
void make_sand_code(char* pyourcode){
  for(int i=0;i<12;i++){
    pyourcode[i]='0'+random(10);
  }
}

//得到奇偶数
void get_odd_even(int* pcode, int* podd, int* peven) {

  //(0,2,4,6,8,10)
  for (int a = 0; a < 6; a++) {
    peven[a] = pcode[a * 2];
  }

  //(1,3,5,7,9,11)
  for (int a = 0; a < 6; a++) {
    podd[a] = pcode[a * 2 + 1];
  }
}

//计算校验位
int calculate_check_digit(int* podd, int* peven) {
  int oddsum = 0;
  int evensum = 0;
  for (int i = 0; i < 6; i++) {
    oddsum += podd[i];
    evensum += peven[i];
  }
  int total = oddsum * 3 + evensum;
  return (10 - (total % 10)) % 10;
}


//正向 和 反向
//1010111011000100100100010011001011001100110010101010000101001110101110011100101000100 1110100 101
//1010010111001000101001110011101011100101000010101010011001100110100110010001001001000 1101110 101


//编码
void encode(char* poutput, int* pcode) {
  char left[42] = { 0 };
  char right[42] = { 0 };
  for (int i = 0; i < 6; i++) {
    for (int a = 0; a < 7; a++) {  //根据第一位判断奇偶
      left[a + i * 7] = encoding_table[pcode[i + 1]][1 - parity_table[pcode[0]][i]][a];
    }
    for (int a = 0; a < 7; a++) {
      right[a + i * 7] = encoding_table[pcode[i + 7]][2][a];
    }
  }

  //101     0111011000100100100010011001011001100110     010101     0100001010011101011100111001010001001110100  101
  //1       4                                            46         51                                           93
  //起始符
  poutput[0] = '1';
  poutput[1] = '0';
  poutput[2] = '1';

  memcpy(poutput + 3, left, 42);

  //中间分隔符
  poutput[45] = '0';
  poutput[46] = '1';
  poutput[47] = '0';
  poutput[48] = '1';
  poutput[49] = '0';

  memcpy(poutput + 50, right, 42);

  //结束符
  poutput[92] = '1';
  poutput[93] = '0';
  poutput[94] = '1';
}

//解码，返回Int数组
void decoding(char* pcode, int* data) {

  //判断方向
  char str[8] = { 0 };
  str[7] = '\0';

  //保存方向
  bool zhengxiang_flag = false;

  //假设最后是校验位，复制到str中
  memcpy(str, pcode + 85, 7);
  //Serial.println(str);
  for (int i = 0; i < 10; i++) {
    for (int a = 0; a < 6; a++) {
      if (strstr(encoding_table[i][2], str) != NULL) {  //只看右边的编码，有的话方向正确
        zhengxiang_flag = true;
        Serial.println("Zheng-xiang!");
        //保存校验位
        data[12] = i;
        break;
      }
    }
  }

  //如果反向
  if (!zhengxiang_flag) {
    Serial.println("Fan-xiang!");
    char temp;
    for (int i = 0; i < 43; i++) {
      temp = pcode[i];
      pcode[i] = pcode[94 - i];
      pcode[94 - i] = temp;
    }
  }

  //开始解右边的数据
  //范围
  //101 011101100010010010001001100101100110011001 01010 1000010 1001110 1011100 1110010 1000100 1110100 101
  //1   4                                          46    51      58      65      72      79      86      93

  for (int b = 0; b < 5; b++) {
    memcpy(str, pcode + 50 + b * 7, 7);
    //打印倒数第N个数字
    // Serial.print(7 + b);
    // Serial.print(":");
    // Serial.print(str);
    //遍历寻找值
    for (int i = 0; i < 10; i++) {
      if (strstr(encoding_table[i][2], str) != NULL) {  //右边的编码
        data[7 + b] = i;
        // Serial.print("  is  ");
        // Serial.println(i);
        break;
      }
    }
  }

  //左侧数据
  //101 0111011 0001001 0010001 0011001 0110011 0011001 01010 1000010 1001110 1011100 1110010 1000100 1110100 101
  //1   4       11      18      25      32      39      46    51      58      65      72      79      86      93

  //判断奇偶模式
  //遍历编码表，记录每个位的奇偶性并找到对于的数字
  int mode[6] = { 0 };
  for (int i = 0; i < 6; i++) {  //左侧6个数字
    memcpy(str, pcode + 3 + i * 7, 7);
    for (int j = 0; j < 10; j++) {
      for (int k = 0; k < 2; k++) {
        if (strstr(encoding_table[j][k], str) != NULL) {
          data[i + 1] = j;
          break;
        }
      }
    }
    for (int a = 0; a < 2; a++) {     //奇偶性
      for (int b = 0; b < 10; b++) {  //0-9数字
        if (strstr(encoding_table[b][a], str) != NULL) {
          mode[i] = 1 - a;
        }
      }
    }
  }

  // Serial.print("mode is:");
  // for (int i = 0; i < 6; i++) {
  //   Serial.print(mode[i]);
  // }
  // Serial.println();

  //匹配奇偶表，找到第一个数字
  //奇偶表的第一个都是1,可以不用判断
  int first_num = 0;
  for (int i = 0; i < 10; i++) {
    if (mode[1] == parity_table[i][1] && mode[2] == parity_table[i][2] && mode[3] == parity_table[i][3] && mode[4] == parity_table[i][4] && mode[5] == parity_table[i][5]) {
      first_num = i;
      break;
    }
  }
  // Serial.print("first num is:");
  // Serial.println(first_num);

  //保存第一个数字
  data[0] = first_num;
}
